home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- next.c
-
- This module handles the next article, thread, and group commands.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include "glob.h"
- #include "article.h"
- #include "newswatcher.h"
- #include "mark.h"
- #include "next.h"
- #include "subject.h"
- #include "listutil.h"
- #include "dialog.h"
- #include "dummy.h"
- #include "help.h"
-
-
-
- /*----------------------------------------------------------------------------
- OpenNextUnreadGroup
-
- Open the subject window for the next group with unread articles in a
- group window.
-
- Entry: wind = pointer to group window.
- theCell = the cell in the group window at which to start
- the search for the next group with unread articles.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr OpenNextUnreadGroup (WindowPtr wind, Cell theCell)
- {
- TWindow **info;
- TGroupWindowKind groupKind;
- TGroup **groupArray, theGroup;
- ListHandle theList;
- short numCells, cellDataLen, index;
- OSErr err = noErr;
- Boolean hasArts;
-
- info = (TWindow**)GetWRefCon(wind);
- groupKind = (**info).groupKind;
- groupArray = (**info).groupArray;
- theList = (**info).theList;
- numCells = (**theList).dataBounds.bottom;
- for (; theCell.v < numCells; theCell.v++) {
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- theGroup = (*groupArray)[index];
- if ((groupKind == kUserGroup && theGroup.unread != nil) ||
- (groupKind != kUserGroup && theGroup.lastMess >= theGroup.firstMess))
- {
- SelectSingleListItem(theList, theCell);
- HandleUpdate(wind);
- MyLAutoScroll(theList);
- err = OpenGroupCell(wind, theCell, gPrefs.maxFetch, &hasArts);
- if (err != noErr) return err;
- if (err == noErr && hasArts) return noErr;
- }
- }
- if (gPrefs.beepAtEndOfLists) SysBeep(0);
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- OpenNextUnreadArticle
-
- Open the article window for the next unread article in a subject window.
-
- Entry: wind = pointer to subject window.
- theCell = the cell in the subject window at which to start
- the search for the next unread article.
- threadOrdinal = ordinal of article within thread at which
- to start the search if the cell is a collapsed thread.
- reuse = pointer to article window to be reused, or nil to
- open new article window.
- onlySelect = true to only select the next unrread article
- in the subject window, but not open it.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr OpenNextUnreadArticle (WindowPtr wind, Cell theCell,
- short threadOrdinal, WindowPtr reuse, Boolean onlySelect)
- {
- TWindow **info;
- TSubject **subjectArray;
- ListHandle theList;
- short numCells, cellDataLen, index, i;
- Boolean collapsed;
- WindowPtr child, parent;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(wind);
- subjectArray = (**info).subjectArray;
- theList = (**info).theList;
- numCells = (**theList).dataBounds.bottom;
- while (theCell.v < numCells) {
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- if (threadOrdinal > (*subjectArray)[index].threadLength) {
- theCell.v++;
- threadOrdinal = 1;
- } else {
- collapsed = (*subjectArray)[index].collapsed;
- if (collapsed)
- for (i = 1; i < threadOrdinal; i++)
- index = (*subjectArray)[index].nextInThread;
- if (!(*subjectArray)[index].read) {
- SelectSingleListItem(theList, theCell);
- HandleUpdate(wind);
- MyLAutoScroll(theList);
- if (onlySelect) return noErr;
- err = OpenSubjectCell(wind, theCell, threadOrdinal, reuse, &child);
- if (err != noErr) return err;
- if (child != nil) return noErr;
- }
- if (collapsed) {
- threadOrdinal++;
- } else {
- theCell.v++;
- threadOrdinal = 1;
- }
- }
- }
- if (reuse != nil) DoClose(reuse);
- if (gPrefs.stopAtEndOfSubjectList) {
- if (gPrefs.beepAtEndOfLists) SysBeep(0);
- } else {
- parent = (**info).parentWindow;
- index = (**info).parentGroup;
- err = DoClose(wind);
- if (err != noErr) return err;
- wind = parent;
- FindParentCell(wind, index, &theCell);
- theCell.v++;
- return OpenNextUnreadGroup(wind, theCell);
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoNextArticle
-
- Handle the "Next Article" command.
-
- Entry: wind = pointer to article, subject, or group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoNextArticle (WindowPtr wind)
- {
- TWindow **info;
- WindowPtr parent;
- short index, threadOrdinal;
- TSubject **subjectArray, theSubject;
- Cell theCell;
- Boolean returnToSubjectWindow = false;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(wind);
-
- switch ((**info).kind) {
-
- case kArticle:
-
- parent = (**info).parentWindow;
- if (parent == nil) return noErr;
- index = (**info).parentSubject;
- info = (TWindow**)GetWRefCon(parent);
- subjectArray = (**info).subjectArray;
- theSubject = (*subjectArray)[index];
- if (theSubject.collapsed) {
- FindParentCell(parent, theSubject.threadHeadIndex, &theCell);
- threadOrdinal = theSubject.threadOrdinal + 1;
- } else {
- FindParentCell(parent, index, &theCell);
- theCell.v++;
- threadOrdinal = 1;
- }
-
- if (gPrefs.returnToSubjectWindow) {
- returnToSubjectWindow = true;
- while (true) {
- if (theSubject.threadOrdinal == theSubject.threadLength) break;
- theSubject = (*subjectArray)[theSubject.nextInThread];
- if (!theSubject.read) {
- returnToSubjectWindow = false;
- break;
- }
- }
- }
-
- if (returnToSubjectWindow) {
- err = DoClose(wind);
- if (err != noErr) return err;
- return OpenNextUnreadArticle(parent, theCell, threadOrdinal, nil, true);
- } else if (gPrefs.reuseArticleWinds) {
- return OpenNextUnreadArticle(parent, theCell, threadOrdinal, wind, false);
- } else {
- err = DoClose(wind);
- if (err != noErr) return err;
- err = ShowDummyWindow();
- if (err != noErr) return err;
- err = OpenNextUnreadArticle(parent, theCell, threadOrdinal, nil, false);
- HideDummyWindow();
- return err;
- }
-
- case kSubject:
-
- SetPt(&theCell, 0, 0);
- LGetSelect(true, &theCell, (**info).theList);
- threadOrdinal = 1;
- return OpenNextUnreadArticle(wind, theCell, threadOrdinal, nil, false);
-
- case kGroup:
-
- SetPt(&theCell, 0, 0);
- LGetSelect(true, &theCell, (**info).theList);
- return OpenNextUnreadGroup(wind, theCell);
-
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoNextThread
-
- Handle the "Next Thread" command.
-
- Entry: wind = pointer to article, subject, or group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoNextThread (WindowPtr wind)
- {
- TWindow **info;
- WindowPtr parent;
- short index, cellDataLen;
- TSubject **subjectArray, theSubject;
- Cell theCell;
- ListHandle theList;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(wind);
-
- switch ((**info).kind) {
-
- case kArticle:
-
- parent = (**info).parentWindow;
- if (parent == nil) return noErr;
- index = (**info).parentSubject;
- info = (TWindow**)GetWRefCon(parent);
- subjectArray = (**info).subjectArray;
- theSubject = (*subjectArray)[index];
- MarkThread(parent, theSubject.threadHeadIndex, true);
- FindParentCell(parent, theSubject.threadHeadIndex, &theCell);
- if (theSubject.collapsed) {
- theCell.v++;
- } else {
- theCell.v += theSubject.threadLength;
- }
-
- if (gPrefs.reuseArticleWinds) {
- return OpenNextUnreadArticle(parent, theCell, 1, wind, false);
- } else {
- err = DoClose(wind);
- if (err != noErr) return err;
- err = ShowDummyWindow();
- if (err != noErr) return err;
- err = OpenNextUnreadArticle(parent, theCell, 1, nil, false);
- HideDummyWindow();
- return err;
- }
-
- case kSubject:
-
- theList = (**info).theList;
- subjectArray = (**info).subjectArray;
- SetPt(&theCell, 0, 0);
- if (LGetSelect(true, &theCell, theList)) {
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- theSubject = (*subjectArray)[index];
- MarkThread(wind, theSubject.threadHeadIndex, true);
- if (theSubject.collapsed) {
- theCell.v++;
- } else {
- theCell.v += theSubject.threadLength + 1 - theSubject.threadOrdinal;
- }
- }
- return OpenNextUnreadArticle(wind, theCell, 1, nil, false);
-
- case kGroup:
-
- SetPt(&theCell, 0, 0);
- LGetSelect(true, &theCell, (**info).theList);
- return OpenNextUnreadGroup(wind, theCell);
-
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoNextGroup
-
- Handle the "Next Group" command.
-
- Entry: wind = pointer to article, subject, or group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoNextGroup (WindowPtr wind)
- {
- TWindow **info;
- WindowPtr parent;
- short index;
- Cell theCell;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(wind);
-
- switch ((**info).kind) {
-
- case kArticle:
-
- parent = (**info).parentWindow;
- if (parent == nil) return noErr;
- err = DoClose(wind);
- if (err != noErr) return err;
- wind = parent;
- info = (TWindow**)GetWRefCon(wind);
- /* fall through to kSubject case */;
-
- case kSubject:
-
- MarkAllSubjects(wind, true);
- parent = (**info).parentWindow;
- index = (**info).parentGroup;
- err = DoClose(wind);
- if (err != noErr) return err;
- wind = parent;
- FindParentCell(wind, index, &theCell);
- theCell.v++;
- return OpenNextUnreadGroup(wind, theCell);
-
- case kGroup:
-
- SetPt(&theCell, 0, 0);
- LGetSelect(true, &theCell, (**info).theList);
- return OpenNextUnreadGroup(wind, theCell);
-
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- OpenPrevOrNextArticle
-
- Open the previous or next article.
-
- Entry: parent = pointer to parent subject window.
- theCell = the parent cell in the subject window for the article.
- threadOrdinal = ordinal of article within thread if thread
- is collapsed, else 1.
- reuse = pointer to article window to be reused, or nil to
- open new article window.
- dir = direction = -1 to open previous article, +1 to open
- next article.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr OpenPrevOrNextArticle (WindowPtr parent, Cell theCell,
- short threadOrdinal, WindowPtr reuse, short dir)
- {
- TWindow **info;
- TSubject **subjectArray;
- ListHandle theList;
- short numCells, cellDataLen, index;
- WindowPtr child;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(parent);
- subjectArray = (**info).subjectArray;
- theList = (**info).theList;
- numCells = (**theList).dataBounds.bottom;
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- while (true) {
- if ((*subjectArray)[index].collapsed) {
- threadOrdinal += dir;
- if (threadOrdinal > (*subjectArray)[index].threadLength) {
- theCell.v++;
- if (theCell.v >= numCells) break;
- threadOrdinal = 1;
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- } else if (threadOrdinal <= 0) {
- theCell.v--;
- if (theCell.v < 0) break;
- LGetCell(&index, &cellDataLen, theCell, theList);
- if ((*subjectArray)[index].collapsed) {
- threadOrdinal = (*subjectArray)[index].threadLength;
- } else {
- threadOrdinal = 1;
- }
- }
- } else {
- theCell.v += dir;
- if (theCell.v >= numCells || theCell.v < 0) break;
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- if (dir == -1 && (*subjectArray)[index].collapsed) {
- threadOrdinal = (*subjectArray)[index].threadLength;
- } else {
- threadOrdinal = 1;
- }
- }
- SelectSingleListItem(theList, theCell);
- HandleUpdate(parent);
- MyLAutoScroll(theList);
- err = OpenSubjectCell(parent, theCell, threadOrdinal, reuse, &child);
- if (err != noErr) return err;
- if (child != nil) return noErr;
- }
- SysBeep(0);
- return noErr;
- }
-
-
- /*----------------------------------------------------------------------------
- GoBackwardsOrForwardsOneArticle
-
- Go backwards or forwards one article.
-
- Entry: wind = pointer to article window.
- dir = direction = -1 to go backwards, +1 to go forwards.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr GoBackwardsOrForwardsOneArticle (WindowPtr wind, short dir)
- {
- TWindow **info;
- WindowPtr parent;
- short index, threadOrdinal;
- TSubject **subjectArray, theSubject;
- Cell theCell;
- Boolean returnToSubjectWindow = false;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(wind);
- if ((**info).kind != kArticle) return noErr;
- parent = (**info).parentWindow;
- if (parent == nil) return noErr;
- index = (**info).parentSubject;
- info = (TWindow**)GetWRefCon(parent);
- subjectArray = (**info).subjectArray;
- theSubject = (*subjectArray)[index];
- if (theSubject.collapsed) {
- FindParentCell(parent, theSubject.threadHeadIndex, &theCell);
- threadOrdinal = theSubject.threadOrdinal;
- } else {
- FindParentCell(parent, index, &theCell);
- threadOrdinal = 1;
- }
- if (gPrefs.reuseArticleWinds) {
- err = OpenPrevOrNextArticle(parent, theCell, threadOrdinal, wind, dir);
- } else {
- err = DoClose(wind);
- if (err != noErr) goto exit;
- err = ShowDummyWindow();
- if (err != noErr) goto exit;
- err = OpenPrevOrNextArticle(parent, theCell, threadOrdinal, nil, dir);
- HideDummyWindow();
- }
-
- exit:
-
- KillBalloon();
- return err;
- }
-